﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Text;
using System.Windows.Forms;

namespace Marmat.Forms.Skin
{
    [Designer("Marmat.Forms.Skin.ButtonGroupDesigner")]
    public partial class ButtonGroup : Control, ISkinControl
    {
        public ButtonGroup()
        {
            InitializeComponent();
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.Buttons = new ButtonGroupItemCollection(this);
            base.BackColor = Color.Transparent;

        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // SkButton
            // 
            this.Name = "ButtonGroup";
            this.Size = new System.Drawing.Size(150, 25);
            this.ResumeLayout(false);

        }


        /// <summary>
        /// 刷新控件的Size
        /// </summary>
        private void RefreshSize()
        {
            if (this.AutoSize && this.Buttons.Count > 0)
            {
                int width = 0;
                foreach (var item in this.Buttons)
                    width += item.Width;
                if (width > 0)
                    this.Width = width;
                this.Invalidate();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            //绘制虚线(只会在设计模式并且AutoSize为False的情况下绘制)
            if (this.DesignMode && !this.AutoSize)
            {
                var thisRec = new Rectangle(0, 0, this.Width - 1, this.Height - 1);
                using (var pen = new Pen(Color.Gray))
                {
                    pen.DashStyle = DashStyle.Dot;
                    e.Graphics.DrawRectangle(pen, thisRec);
                }
            }
            this.rectangleDec.Clear();
            //优化绘制质量
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高，即消除锯齿
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            int width = 0;
            var first = this.Buttons.FirstOrDefault();
            var last = this.Buttons.LastOrDefault();
            foreach (var item in this.Buttons)
            {
                Rectangle rec = new Rectangle(width, 0, item.Width, this.Height-1);
                GraphicsPath btnPath;
                int cir = this.round ? Math.Min(rec.Width, rec.Height) / 2 : this._circle;
                if (item != last && item != first)
                    btnPath = rec.GetRoundPath(0);
                else if (this.Buttons.Count == 1)
                    btnPath = rec.GetRoundPath(cir);
                else if (first == item)
                {
                    //修正抗锯齿带来的偏移
                    rec.Width--;
                    btnPath = rec.GetRoundPath(cir, 0, cir, 0);
                }
                else
                {
                    //修正抗锯齿带来的偏移
                    rec.Width--;
                    btnPath = rec.GetRoundPath(0, cir, 0, cir);
                }
                using (var bush = new SolidBrush(GetFouseColor(rec, item)))
                    e.Graphics.FillPath(bush, btnPath);
                DrawTextAndIcon(e.Graphics, item, width);
                width += item.Width;
                this.rectangleDec[item] = rec;
            }
            if (width > 0 && this.AutoSize)
                this.Width = width;
        }


        /// <summary>
        /// 获取焦点颜色
        /// </summary>
        private Color GetFouseColor(Rectangle rec, ButtonGroupItem button)
        {
            Color back_color = button.BackColor;
            if (!button.Enabled || !this.Enabled)
                back_color = button.BackColor.Blend(Color.FromArgb(Convert.ToInt32(256 * 0.5), Color.White));
            else if (rec.Contains(point) && this.clickButton == button)
                back_color = button.BackColor.Blend(Color.FromArgb(Convert.ToInt32(255 * 0.1), Color.Black));
            else if (rec.Contains(point))
                back_color = button.BackColor.Blend(Color.FromArgb(Convert.ToInt32(255 * 0.2), Color.White));
            return back_color;
        }

        /// <summary>
        /// 绘制Icon与Text
        /// </summary>
        private void DrawTextAndIcon(Graphics graphics, ButtonGroupItem button, int x)
        {
            Size icon_size = default;
            Size text_size = default;
            if (button.Image != null)
                icon_size = new Size(Math.Min(button.Image.Width, this.Font.Height), Math.Min(button.Image.Height, this.Font.Height));
            if (!string.IsNullOrEmpty(button.Text))
                text_size = TextRenderer.MeasureText(button.Text, this.Font);
            int item_x = (button.Width - icon_size.Width - text_size.Width) / 2;

            var bitmap = new Bitmap(button.Width, this.Height);
            var gra = Graphics.FromImage(bitmap);
            gra.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高，即消除锯齿
            gra.InterpolationMode = InterpolationMode.HighQualityBicubic;
            gra.CompositingQuality = CompositingQuality.HighQuality;
            gra.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            if (button.TextImageRelation == TextImageRelation.ImageBeforeText)
            {
                draw_icon();
                draw_text();
            }
            else
            {
                draw_text();
                draw_icon();
            }
            graphics.DrawImage(bitmap, new Rectangle(x, 0, button.Width, this.Height));
            void draw_text()
            {
                if (!string.IsNullOrEmpty(button.Text))
                {
                    var rect = new Rectangle(item_x, (this.Height - text_size.Height) / 2, text_size.Width, text_size.Height);
                    using (var bush = new SolidBrush(this.ForeColor))
                    {
                        StringFormat format = new StringFormat();
                        format.Alignment = StringAlignment.Center;
                        format.LineAlignment = StringAlignment.Center;
                        gra.DrawString(button.Text, this.Font, bush, rect, format);
                    }
                    item_x += text_size.Width;
                }
            }
            void draw_icon()
            {
                if (button.Image != null)
                {
                    gra.DrawImage(button.Image, new Rectangle(item_x, (this.Height - icon_size.Height) / 2, icon_size.Width, icon_size.Height));
                    item_x += icon_size.Width;

                }
            }
        }

        /// <summary>
        /// 鼠标在控件可视区域移动
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            point = e.Location;
            this.Invalidate();
            base.OnMouseMove(e);
        }

        /// <summary>
        /// 鼠标离开控件可视区域
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            point.X = -1;
            point.Y = -1;
            this.Invalidate();
            base.OnMouseLeave(e);
        }

        /// <summary>
        /// 鼠标点击
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                foreach (var recItme in rectangleDec)
                {
                    if (recItme.Value.Contains(e.Location))
                    {
                        this.clickButton = recItme.Key;
                        this.Invalidate();
                        return;
                    }
                }
            }
            base.OnMouseDown(e);
        }


        /// <summary>
        /// 鼠标抬起
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            this.clickButton = null;
            if (e.Button == MouseButtons.Left)
            {
                foreach (var recItme in rectangleDec)
                {
                    if (recItme.Value.Contains(e.Location))
                    {
                        var args = new ButtonGroupEventArgs(recItme.Key);
                        this.ItemClicked?.Invoke(this, args);
                        this.Invalidate();
                        return;
                    }
                }
            }
            base.OnMouseUp(e);
        }
    }
}
